我在這篇文章分別示範用 Nx CLI 和 Angular CLI 去建立 Angular SSR專案。其實在下筆寫這篇文章的一開始,我用 Nx CLI 要設定 SSR 一直撞牆。但是我後來在網路上看到這篇教學文章,抱著「最後一試」的心情實作,居然成功了!
以下就分享一下我的實作歷程~
我試著開了許多不同的視窗,不斷詢問ChatGPT要怎麼在 Nx 建立 Angular SSR,最終都以失敗告終。我們先來看第一版建議:
步驟 1:建立Nx Monorepo 專案
開啟命令列,使用以下命令建立一個新的Nx monorepo專案:
npx create-nx-workspace my-ssr-app
這將引導你通過一些選項來設定專案,請確保選擇Angular作為你的主要前端框架。
完成專案建立後,你可以使用以下命令來建立一個新的Angular應用程式:
ng generate application my-app
步驟 2:安裝Angular Universal
Angular Universal是Angular的官方SSR解決方案。你需要安裝它以實現SSR功能。
在專案根目錄下,使用以下命令來安裝Angular Universal:ng add @nguniversal/express-engine
這個命令會安裝必要的套件並設定一些基本的SSR結構。
步驟 3:設定SSR相關文件
在你的Angular應用程式中,你會看到一個src資料夾,裡面有一個main.ts檔案。請將它改為main.server.ts。創建一個新的Express應用程式,並設定SSR的路由和中間件。你可以在server.ts檔案中進行這些設定。在app.server.module.ts檔案中,確保你已經設定好了ServerModule和相關的Angular Universal模組。
....
從這裡不難發現,它在步驟一就錯了。當你用 Nx CLI 建立專案的時候,是不能和 Angular CLI 混用的。你在 Nx專案下打 ng
開頭的指令都會報錯。但是在Nx專案下,又必須使用 Nx CLI。
再來就是,手動設定SSR相關文件完全是個坑。原本提到可能要手動設定SSR,但實際頭洗下去實作後發現,這等於進入另一個實作迷宮。評估後,我認為最好用打指令的方式一次性的去建立SSR相關配置會比較好,手動設定的細節太多了,很容易因為一個小地方沒設定好而一直失敗。
.
.
.
這裡就簡單多了,我基本上就是照著ChatGPT的指示,一次就過:
ng new angular-ssr-app
.
ng add @nguniversal/express-engine
.
ng generate universal --client-project angular-ssr-app
如果你是比較新的版本(我實作的時候是Angular 16),打這個指令應該會出錯。
ChatGPT表示新版本的Angular CLI中, --client-project
這個參數已不再使用。當你打 ng add @nguniversal/express-engine
這個指令時,會自動設定Angular Universal相關的設定,不需要再手動指定--client-project參數。
.
ng g c server-rendered
這裡也出現一個小插曲,因為我預設是standalone模式,所以沒有指定要放在Module,又沒有告知不用放到任何Module時,這裡就會報錯。
正確寫法如下, --skip-import
就是告知「不用放到任何Module」的意思:
ng g c server-rendered --skip-import
.
就是一般我們要設定路由指向哪個component的地方做設定
// src/app/app-routing.module.ts
const routes: Routes = [
{
path: 'server-rendered',
loadComponent: () => import('./server-rendered/server-rendered.component')
// 這裡省略了then以後,在 ServerRenderedComponent 的 export 後面要加 default
}
];
.
在使用Angular Universal的時候,我們還需要在 server.ts
也設定路由:
server.get('*.*', express.static(distFolder, {
maxAge: '1y'
}));
// 在這裡添加各頁面的路由! 在這裡添加各頁面的路由! 在這裡添加各頁面的路由!
server.get('/server-rendered', (req, res) => {
res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
});
server.get('*', (req, res) => {
res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
});
.
ng build
ng run angular-ssr-app:server
node dist/angular-ssr-app/server/main.js
在瀏覽器測試成功的畫面:
.
.
.
前面提到我跟著網路文章實作成功,以下就來分享這個過程:
cd /Users/chiawenfang/Desktop
npx create-nx-workspace nx-ssr-app
ps. 我一開始忘了cd到桌面,因此我是先建立 Nx workspace 後,手動拖到桌面的。
.
cd /Users/chiawenfang/Desktop/nx-ssr-app
npx nx generate @nrwl/angular:app MyApp
.
npx ng add @nguniversal/express-engine --clientProject my-app
這裡出現了跟剛剛一樣的錯誤,因此我推斷應該是已經建好Angular Universal了。打開VsCode看專案結構,發現的確已經配置好SSR的相關設定了!
.
npx nx run nx-ssr-app:serve
nx run nx-ssr-app:serve-ssr
在瀏覽器測試成功的畫面:
.
.
.
除了打開 http://localhost:4000
以外,還有其它的方法可以知道自己有沒有成功設定SSR嗎?
有的,根據ChatGPT的回答,我們有這四種方法:
能看到 該元件
完整的Html,而不是只有 index.html
上的Html
.
尚未設定SSR前,會需要等待JS檔下載完成才看得到頁面內容。但使用SSR的時候,在server端已經先把頁面檔跟js都載好、合起來,才一併送到Client端。因此,重新載入後的第一個畫面,照理說就可以看到內容囉!
.
如果有正常設定SSR的話,禁用JS後重新載入畫面,應該也要能正常顯示。以剛剛用 Nx 建立 SSR 專案為例,如果我只有打 npx nx run nx-ssr-app:serve
。那禁用JS後會一片空白如下:
要把伺服器端的程式碼也build好,才會正常。
.
還記得我們前面提到說SSR是解決SEO的方法之一嗎? 我們未設定前,Google爬蟲爬到我們網頁是一片空白,但現在做了SSR設定後,應該會爬到完整的頁面內容。這裡需要用一些SEO工具,例如「Google Search Console」的「模擬爬蟲(etch as Google)」。
.
.
.
總算對自己有個交代了XD